home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / glimpse-2.1 / index / partition.c < prev    next >
C/C++ Source or Header  |  1995-05-16  |  21KB  |  637 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* ./glimpse/index/partition.c */
  3. #include "glimpse.h"
  4. #include <sys/stat.h>
  5.  
  6. extern char INDEX_DIR[MAX_LINE_LEN];
  7. extern int file_num;    /* the number of files */
  8. extern char *name_list[MAX_LIST];    /* to store the file names */
  9. extern int  *size_list;    /* store size of each file */
  10. extern int  p_table[MAX_PARTITION];    /* partition table, the i-th partition begins at p_table[i] and ends at p_tables[i+1] */
  11. extern int  p_size_list[MAX_PARTITION];    /* sum of the sizes of the files in each partition */
  12. extern int  part_num;    /* number of partitions, 1 initially since partition # 0 is not accessed */
  13.  
  14. extern int total_size; /* total size of the directory */
  15. int  part_size=DEFAULT_PART_SIZE;    /* partition size */
  16. int  new_partition;
  17. int  files_per_partition;
  18. int  files_in_partition;
  19.  
  20. char patbuf[MAX_PAT];
  21. extern unsigned char src_index_buf[REAL_INDEX_BUF];
  22. extern unsigned char dest_index_buf[REAL_INDEX_BUF];
  23. extern int memory_usage;
  24.  
  25. extern  FILE    *STATFILE;
  26. extern  FILE    *MESSAGEFILE;
  27.  
  28. extern struct stat excstbuf;
  29. extern struct stat incstbuf;
  30.  
  31. extern int OneFilePerBlock;
  32. extern int ByteLevelIndex;
  33. extern int StructuredIndex;
  34. extern int attr_num;
  35. extern char INDEX_DIR[MAX_LINE_LEN];
  36. extern int AddToIndex;
  37. extern int IndexableFile;
  38.  
  39. char *exin_argv[8];
  40. int exin_argc;
  41. char current_dir_buf[2*MAX_LINE_LEN + 4];    /* must have space to store pattern after directory name */
  42. unsigned char dummypat[MAX_PAT];
  43. int dummylen;
  44. FILE *dummyout;
  45.  
  46. partition(dir_num, dir_name)
  47. char **dir_name;
  48. int  dir_num;
  49. {
  50.     int num_pat=0;
  51.     int num_inc=0;
  52.     int len;
  53.     int  pat_len[MAX_EXCLUSIVE];
  54.     int  inc_len[MAX_EXCLUSIVE];
  55.     CHAR *inc[MAX_INCLUSIVE];    /* store the patterns used to mask in files */
  56.     CHAR *pat[MAX_EXCLUSIVE];     /* store the patterns that are used to
  57.                      mask out those files that are not to
  58.                      be indexed  */
  59.     int MinPartNum;         /* minimum number of partitions */
  60.     int i=0, j;
  61.     int subtotal=0;
  62.     int pdx = 0;             /* index pointer for p_table */
  63.     FILE *patfile;     /* file descriptor for prohibit pattern file */
  64.     FILE *incfile;    /* file descriptor for include pattern file */
  65.     char *current_dir;    /* must have '\n' before directory name */
  66.     char s[MAX_LINE_LEN];
  67.     char working_dir[MAX_LINE_LEN];
  68.     struct stat sbuf;
  69.  
  70.     current_dir_buf[0] = '\n';
  71.     current_dir_buf[1] = '\0';
  72.     current_dir = ¤t_dir_buf[1];
  73.     /* if (IndexableFile) goto directlytofsize; */
  74.  
  75.     if ((dummyout = fopen("/dev/null", "w")) == NULL) return -1;
  76.     exin_argv[0] = "glimpseindex";
  77.     exin_argv[1] = "dummypat";
  78.     exin_argc = 2;
  79.     if ((dummylen = memagrep_init(exin_argc, exin_argv, MAX_PAT, dummypat)) <= 0) return -1;    /* exclude/include pattern search */
  80.  
  81.     sprintf(s, "%s/%s", INDEX_DIR, PROHIBIT_LIST);
  82.     patfile = fopen(s, "r");
  83.     if(patfile == NULL) {
  84.     /* fprintf(stderr, "can't open exclude-pattern file\n"); -- no need! */
  85.     num_pat = 0;
  86.     }
  87.     else {
  88.     while((num_pat < MAX_EXCLUSIVE) && fgets(patbuf, MAX_PAT, patfile)) {
  89.         if ((len = strlen(patbuf)) < 1) continue;
  90.         patbuf[len-1] = '\0';
  91.         if ((pat_len[num_pat] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  92.         pat[num_pat++] = (unsigned char *) strdup(patbuf);
  93.     }
  94.     fclose(patfile);
  95.     }
  96. #if    0
  97.     printf("num_pat %d\n", num_pat);
  98.     for(i=0; i<num_pat; i++) printf("len=%d pat=%s\n", pat_len[i], pat[i]);
  99.     printf("memagrep=%d\n", memagrep_search(-pat_len[0], pat[0], 17, "\n.glimpse_index\nasdfk", 0, stdout));
  100. #endif
  101.  
  102.     sprintf(s, "%s/%s", INDEX_DIR, INCLUDE_LIST);
  103.     incfile = fopen(s, "r");
  104.     if(incfile == NULL) {
  105.     /* fprintf(stderr, "can't open include-pattern file\n"); -- no need! */
  106.     num_inc = 0;
  107.     }
  108.     else {
  109.     while((num_inc < MAX_INCLUSIVE) && fgets(patbuf, MAX_PAT, incfile)) {
  110.         if ((len = strlen(patbuf)) < 1) continue;
  111.         patbuf[len-1] = '\0';
  112.         if ((inc_len[num_inc] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  113.         inc[num_inc++] = (unsigned char *) strdup(patbuf);
  114.     }
  115.     fclose(incfile);
  116.     }
  117. #if    0
  118.     printf("num_inc %d\n", num_inc);
  119.     for(i=0; i<num_inc; i++) printf("len=%d inc=%s\n", inc_len[i], inc[i]);
  120. #endif
  121.  
  122. #ifdef    SW_DEBUG
  123.     printf("dir_num = %d", dir_num-1);
  124. #endif
  125. directlytofsize:
  126.     if (dir_num <= 1) while (fgets(current_dir, MAX_LINE_LEN, stdin) == current_dir) {
  127.     current_dir[strlen(current_dir)-1] = '\0';    /* overwrite \n with \0 */
  128.  
  129.     /* Get absolute path name of the directory or file being indexed */
  130.     if (-1 == stat(current_dir, &sbuf)) {
  131.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  132.         continue;
  133.     }
  134.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  135.         getcwd(working_dir, MAX_LINE_LEN - 1);
  136.         if (-1 == chdir(current_dir)) {
  137.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  138.         continue;
  139.         }
  140.         getcwd(current_dir, MAX_LINE_LEN - 1);
  141.         chdir(working_dir);
  142.     }
  143.  
  144.     if (!IndexableFile) printf("Indexing \"%s\" ...\n", current_dir);
  145.         fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1); /* the file names will be in name_list[] */
  146.     }
  147.     else for(i=1; i<dir_num; i++) {
  148.         strcpy(current_dir, dir_name[i]);
  149.  
  150.     /* Get absolute path name of the directory or file being indexed */
  151.     if (-1 == stat(current_dir, &sbuf)) {
  152.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  153.         continue;
  154.     }
  155.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  156.         getcwd(working_dir, MAX_LINE_LEN - 1);
  157.         if (-1 == chdir(current_dir)) {
  158.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  159.         continue;
  160.         }
  161.         getcwd(current_dir, MAX_LINE_LEN - 1);
  162.         chdir(working_dir);
  163.     }
  164.  
  165.     if (!IndexableFile) printf("Indexing \"%s\" ...\n", current_dir);
  166.         fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1); /* the file names will be in name_list[] */
  167.     }
  168.     if (IndexableFile) return 0;
  169.  
  170.     for(i=0; i<file_num; i++) total_size += size_list[i];
  171.     fprintf(STATFILE, "Size of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);
  172.     printf("\nSize of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);    /* the only output the user sees */
  173.  
  174. #ifdef    SW_DEBUG
  175.     for (i=0; i<file_num; i++)
  176.     printf("name_list[%d] = %s, size=%d\n", i, name_list[i], size_list[i]);
  177. #endif    /*SW_DEBUG*/
  178.  
  179.     for (i=0; i<num_inc; i++) {
  180. #if    BG_DEBUG
  181.     memory_usage -= strlen(inc) + 2;
  182. #endif    /*BG_DEBUG*/
  183.     my_free(inc[i], 0);
  184.     }
  185.     for (i=0; i<num_pat; i++) {
  186. #if    BG_DEBUG
  187.     memory_usage -= strlen(pat) + 2;
  188. #endif    /*BG_DEBUG*/
  189.     my_free(pat[i], 0);
  190.     }
  191.  
  192.     /* Life (algorithm) is much simpler, but encode/decode (I/O) is more complex: the p_table is irrelevant */
  193.     if (OneFilePerBlock)
  194.     return 0;
  195.  
  196.     /* Now put the files into partitions */
  197.     i=0;
  198.     part_size = total_size / MaxNumPartition;
  199.     if (part_size <= 0) part_size = total_size;
  200.     size_list[file_num] = part_size;
  201.     if (file_num / 2 <= 1) {
  202.     p_table[0] = 0;
  203.     p_table[1] = 0;
  204.     p_table[2] = file_num;
  205.     part_num = 2;
  206.     return 0;
  207.     }
  208.  
  209.     MinPartNum = (200 < file_num/2)? 200 : file_num/2;
  210.     while(part_num < MinPartNum) {
  211.         pdx = 0;
  212.     i = 0;
  213.         subtotal = 0;
  214.         while ((i < file_num) && (pdx < MAX_PARTITION)) {
  215.         if((pdx == 0) || (pdx == '\n')) {
  216.         /*
  217.          * So that there cannot be a partition #'\n' and a '\n' can indicate
  218.          * the end of the list of partition#s after the WORD_END_MARK.
  219.          * Also, partition#0 is not accessed so that sort does not
  220.          * ignore the partitions after partition# 0!
  221.          */
  222.         p_table[pdx++] = i;
  223.         continue;
  224.         }
  225.         p_table[pdx++] = i;
  226.             while(subtotal < part_size) {
  227.                 subtotal += size_list[i++];
  228.             }
  229. #ifdef    SW_DEBUG
  230.         printf("pdx=%d part_num=%d i=%d subtotal=%d\n", pdx, part_num, i, subtotal);
  231. #endif
  232.             subtotal = 0;
  233.         }
  234.     part_num = pdx;
  235. #if    0
  236.     printf("part_num = %d part_size = %d\n", part_num, part_size);
  237. #endif
  238.     part_size = part_size * 0.9;
  239.         size_list[file_num] = part_size;
  240.     }
  241.     p_table[pdx] = file_num;
  242.  
  243.     /* Calculate partition sizes for later output into statistics */
  244.     for (i=0; i<= part_num; i++)
  245.     for (j = p_table[i]; j<p_table[i+1]; j++)
  246.         p_size_list[i] += size_list[j];
  247.  
  248.     return 0;
  249. }
  250.  
  251. int printed_warning = 0;
  252.  
  253. /*
  254.  * Difference from above: does not build a new partition table:
  255.  * adds to the existing one (see glimpse.c, options -a and -f).
  256.  * -- added on dec 7th '93
  257.  */
  258. oldpartition(dir_num, dir_name)
  259. char **dir_name;
  260. int  dir_num;
  261. {
  262.     int num_pat=0;
  263.     int num_inc=0;
  264.     int len;
  265.     int  pat_len[MAX_EXCLUSIVE];
  266.     int  inc_len[MAX_EXCLUSIVE];
  267.     CHAR *inc[MAX_INCLUSIVE];    /* store the patterns used to mask in files */
  268.     CHAR *pat[MAX_EXCLUSIVE];     /* store the patterns that are used to
  269.                      mask out those files that are not to
  270.                      be indexed  */
  271.     int i=0;
  272.     FILE *patfile;     /* file descriptor for prohibit pattern file */
  273.     FILE *incfile;    /* file descriptor for include pattern file */
  274.     char *current_dir;    /* must have '\n' before directory name */
  275.     char s[MAX_LINE_LEN];
  276.     char working_dir[MAX_LINE_LEN];
  277.     struct stat sbuf;
  278.  
  279.     current_dir_buf[0] = '\n';
  280.     current_dir_buf[1] = '\0';
  281.     current_dir = ¤t_dir_buf[1];
  282.  
  283.     if ((dummyout = fopen("/dev/null", "w")) == NULL) return -1;
  284.     exin_argv[0] = "glimpseindex";
  285.     exin_argv[1] = "dummypat";
  286.     exin_argc = 2;
  287.     if ((dummylen = memagrep_init(exin_argc, exin_argv, MAX_PAT, dummypat)) <= 0) return -1;    /* exclude/include pattern search */
  288.  
  289.     sprintf(s, "%s/%s", INDEX_DIR, PROHIBIT_LIST);
  290.     patfile = fopen(s, "r");
  291.     if(patfile == NULL) {
  292.     /* fprintf(stderr, "can't open exclude-pattern file\n"); -- no need! */
  293.     num_pat = 0;
  294.     }
  295.     else {
  296.     stat(s, &excstbuf);
  297.     while((num_pat < MAX_EXCLUSIVE) && fgets(patbuf, MAX_PAT, patfile)) {
  298.         if ((len = strlen(patbuf)) < 1) continue;
  299.         patbuf[len-1] = '\0';
  300.         if ((pat_len[num_pat] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  301.         pat[num_pat++] = (unsigned char *) strdup(patbuf);
  302.     }
  303.     fclose(patfile);
  304.     }
  305. #if    0
  306.     printf("num_pat %d\n", num_pat);
  307.     for(i=0; i<num_pat; i++) printf("len=%d pat=%s\n", pat_len[i], pat[i]);
  308. #endif
  309.  
  310.     sprintf(s, "%s/%s", INDEX_DIR, INCLUDE_LIST);
  311.     incfile = fopen(s, "r");
  312.     if(incfile == NULL) {
  313.     /* fprintf(stderr, "can't open include-pattern file\n"); -- no need! */
  314.     num_inc = 0;
  315.     }
  316.     else {
  317.     stat(s, &incstbuf);
  318.     while((num_inc < MAX_INCLUSIVE) && fgets(patbuf, MAX_PAT, incfile)) {
  319.         if ((len = strlen(patbuf)) < 1) continue;
  320.         patbuf[len-1] = '\0';
  321.         if ((inc_len[num_inc] = convert2agrepregexp(patbuf, len-1)) == 0) continue;
  322.         inc[num_inc++] = (unsigned char *) strdup(patbuf);
  323.     }
  324.     fclose(incfile);
  325.     }
  326. #if    0
  327.     printf("num_inc %d\n", num_inc);
  328.     for(i=0; i<num_inc; i++) printf("len=%d inc=%s\n", inc_len[i], inc[i]);
  329. #endif
  330.  
  331. #ifdef    SW_DEBUG
  332.     printf("dir_num = %d part_num = %d", dir_num-1, part_num);
  333. #endif
  334.  
  335.     if (!OneFilePerBlock) {    /* Worry about partitions */
  336.     files_per_partition = ((file_num - 1)/part_num) + 1;    /* approximate only but gives a fair idea... */
  337.     files_in_partition = 0;
  338.     new_partition = part_num;    /* part_num itself is guaranteed to be <= MaxNumPartition */
  339.  
  340.     if (new_partition + 1 > MaxNumPartition) {
  341.         printed_warning = 1;
  342.         if (AddToIndex) {
  343.         fprintf(MESSAGEFILE, "Warning: partition-table overflow! Fresh indexing recommended.\n");
  344.         }
  345.         else {
  346.         fprintf(MESSAGEFILE, "Warning: partition-table overflow! Commencing fresh indexing...\n");
  347.         return partition(dir_num, dir_name);
  348.         }
  349.     }
  350.     }
  351.  
  352.     if (dir_num <= 1) while (fgets(current_dir, MAX_LINE_LEN, stdin) == current_dir) {
  353.     current_dir[strlen(current_dir)-1] = '\0';    /* overwrite \n with \0 */
  354.  
  355.     /* Get absolute path name of the directory or file being indexed */
  356.     if (-1 == stat(current_dir, &sbuf)) {
  357.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  358.         continue;
  359.     }
  360.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  361.         getcwd(working_dir, MAX_LINE_LEN - 1);
  362.         if (-1 == chdir(current_dir)) {
  363.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  364.         continue;
  365.         }
  366.         getcwd(current_dir, MAX_LINE_LEN - 1);
  367.         chdir(working_dir);
  368.     }
  369.  
  370.     printf("Indexing \"%s\" ...\n", current_dir);
  371.         fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1); /* the file names will be in name_list[] */
  372.     }
  373.     else for(i=1; i<dir_num; i++) {
  374.         strcpy(current_dir, dir_name[i]);
  375.  
  376.     /* Get absolute path name of the directory or file being indexed */
  377.     if (-1 == stat(current_dir, &sbuf)) {
  378.         fprintf(stderr, "permission denied or non-existent: %s\n", current_dir);
  379.         continue;
  380.     }
  381.     if ((S_ISDIR(sbuf.st_mode)) && (current_dir[0] != '/')) {
  382.         getcwd(working_dir, MAX_LINE_LEN - 1);
  383.         if (-1 == chdir(current_dir)) {
  384.         fprintf(stderr, "Cannot chdir to %s\n", current_dir);
  385.         continue;
  386.         }
  387.         getcwd(current_dir, MAX_LINE_LEN - 1);
  388.         chdir(working_dir);
  389.     }
  390.  
  391.     printf("Indexing \"%s\" ...\n", current_dir);
  392.         if (-1 == fsize(current_dir, pat, pat_len, num_pat, inc, inc_len, num_inc, 1)) { /* the file names will be in name_list[] */
  393.         return -1;
  394.     }
  395.     }
  396.  
  397.     if (!OneFilePerBlock) {
  398.     p_table[new_partition] = file_num;
  399.     part_num = new_partition;
  400.     }
  401.  
  402.     for (i=0; i<num_inc; i++) {
  403. #if    BG_DEBUG
  404.     memory_usage -= strlen(inc) + 2;
  405. #endif    /*BG_DEBUG*/
  406.     my_free(inc[i], 0);
  407.     }
  408.     for (i=0; i<num_pat; i++) {
  409. #if    BG_DEBUG
  410.     memory_usage -= strlen(pat) + 2;
  411. #endif    /*BG_DEBUG*/
  412.     my_free(pat[i], 0);
  413.     }
  414.  
  415.     for(i=0; i<file_num; i++) total_size += size_list[i];
  416.     fprintf(STATFILE, "Size of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);
  417.     printf("\nSize of files being indexed = %d B, Total #of files = %d\n", total_size, file_num);    /* the only output the user sees */
  418.  
  419. #ifdef    SW_DEBUG
  420.     for (i=0; i<file_num; i++)
  421.     printf("name_list[%d] = %s, size=%d\n", i, name_list[i], size_list[i]);
  422. #endif    /*SW_DEBUG*/
  423.  
  424.     return 0;
  425. }
  426.  
  427. save_data_structures()
  428. {
  429.     int    i;
  430.     char s[MAX_LINE_LEN];
  431.     FILE *f_out;
  432.     FILE *p_out;
  433.     int j;
  434.     unsigned char c;
  435.     FILE *i_in;
  436.     FILE *i_out;
  437.     int offset, index, wordoffset;
  438.     char indexnumberbuf[256];
  439.     int    onefileperblock, structuredindex;
  440.  
  441.     /* Dump attributes */
  442.     if (StructuredIndex) {
  443.     int    ret;
  444.     sprintf(s, "%s/%s", INDEX_DIR, ATTRIBUTE_FILE);
  445.     if (-1 == (ret = attr_dump_names(s))) {
  446.         fprintf(stderr, "can't open %s for writing\n", s);
  447.         exit(2);
  448.     }
  449.     }
  450.  
  451.     /* Dump partition table; change index if necessary */
  452.     sprintf(s, "%s/%s", INDEX_DIR, P_TABLE);
  453.     if((p_out = fopen(s, "w")) == NULL) {
  454.     fprintf(stderr, "can't open for writing: %s\n", s);
  455.     exit(2);
  456.     }
  457.     if (!OneFilePerBlock) {
  458. #ifdef SW_DEBUG
  459.     printf("part_num = %d, part_size = %d\n", part_num, part_size);
  460. #endif
  461.     for(i=0; i<=part_num; i++) {
  462.         /* Assumes sizeof(int) is 32bits, which is true even for ALPHA */
  463.         putc((p_table[i] & 0xff000000) >> 24, p_out);
  464.         putc((p_table[i] & 0x00ff0000) >> 16, p_out);
  465.         putc((p_table[i] & 0x0000ff00) >> 8, p_out);
  466.         if (putc((p_table[i] & 0x000000ff), p_out) == EOF) {
  467.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  468.         exit(2);
  469.         }
  470.         if (i==part_num) break;
  471.         if (p_table[i] == p_table[i+1]) {
  472.         fprintf(STATFILE, "part_num = %d, files = none, part_size = 0\n",i);
  473.         continue;
  474.         }
  475.         fprintf(STATFILE, "part_num = %d, files = %d .. %d, part_size = %d\n",
  476.         i, p_table[i], p_table[i+1] - 1, p_size_list[i]);
  477.     }
  478.  
  479.     if (StructuredIndex) {    /* check if we can reduce default 4B attributeids to smaller ones */
  480.         sprintf(s, "%s/.glimpse_split.%d", INDEX_DIR, getpid());
  481.         if((i_out = fopen(s, "w")) == NULL) {
  482.         fprintf(stderr, "can't open %s for writing\n", s);
  483.         exit(2);
  484.         }
  485.         sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  486.         if((i_in = fopen(s, "r")) == NULL) {
  487.         fprintf(stderr, "can't open %s for reading\n", s);
  488.         exit(2);
  489.         }
  490.  
  491.         /* modified the original in glimpse's main.c */
  492.         fgets(indexnumberbuf, 256, i_in);
  493.         fputs(indexnumberbuf, i_out);
  494.         fscanf(i_in, "%%%d\n", &onefileperblock);
  495.         fprintf(i_out, "%%%d\n", onefileperblock);    /* If #of files change, then they are added to a new partition, which is updated above */
  496.         fscanf(i_in, "%%%d\n", &structuredindex);
  497.         if (structuredindex <= 0) structuredindex = 0;
  498.         fprintf(i_out, "%%%d\n", attr_num);    /* attributes might have been added during last merge */
  499.  
  500.         while(fgets(src_index_buf, REAL_INDEX_BUF, i_in)) {
  501.         if ((index=decode32b((src_index_buf[0] << 24)|(src_index_buf[1] << 16)|(src_index_buf[2] << 8)|(src_index_buf[3]))) > attr_num) continue;
  502.         if (attr_num < MaxNum8bPartition - 1) {
  503.             putc(encode8b(index), i_out);
  504.             if (fputs(src_index_buf + 4, i_out) == EOF) {
  505.             fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  506.             exit(2);
  507.             }
  508.         }
  509.         else if (attr_num < MaxNum16bPartition - 1) {
  510.             index = encode16b(index);
  511.             putc((index & 0x0000ff00) >> 8, i_out);
  512.             putc(index & 0x000000ff, i_out);
  513.             if (fputs(src_index_buf + 4, i_out) == EOF) {
  514.             fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  515.             exit(2);
  516.             }
  517.         }
  518.         else {
  519.             if (fputs(src_index_buf, i_out) == EOF) {    /* no reduction */
  520.             fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  521.             exit(2);
  522.             }
  523.         }
  524.         }
  525.  
  526.         fclose(i_in);
  527.         fflush(i_out);
  528.         fclose(i_out);
  529.         sprintf(s, "mv %s/.glimpse_split.%d %s/%s", INDEX_DIR, getpid(), INDEX_DIR, INDEX_FILE);
  530.         system(s);
  531.     }
  532.     }
  533.     else {
  534.     /* Don't care about individual file sizes in statistics since the user can look at it anyway by ls -l! */
  535.     sprintf(s, "%s/.glimpse_split.%d", INDEX_DIR, getpid());
  536.         if((i_out = fopen(s, "w")) == NULL) {
  537.         fprintf(stderr, "can't open %s for writing\n", s);
  538.         exit(2);
  539.         }
  540.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  541.         if((i_in = fopen(s, "r")) == NULL) {
  542.         fprintf(stderr, "can't open %s for reading\n", s);
  543.         exit(2);
  544.         }
  545.  
  546.         /* modified the original in glimpse's main.c */
  547.         fgets(indexnumberbuf, 256, i_in);
  548.         fputs(indexnumberbuf, i_out);
  549.         fscanf(i_in, "%%%d\n", &onefileperblock);
  550.         if (ByteLevelIndex) fprintf(i_out, "%%-%d\n", file_num);    /* #of files might have changed due to -f/-a */
  551.     else fprintf(i_out, "%%%d\n", file_num);    /* This was the stupidest thing of all! */
  552.         fscanf(i_in, "%%%d\n", &structuredindex);
  553.         if (structuredindex <= 0) structuredindex = 0;
  554.         fprintf(i_out, "%%%d\n", attr_num);    /* attributes might have been added during last merge */
  555.  
  556.     part_size = 0;    /* current offset in the p_table file */
  557.     while(fgets(src_index_buf, REAL_INDEX_BUF, i_in)) {
  558.         if (StructuredIndex) {
  559.         if ((index=decode32b((src_index_buf[0] << 24)|(src_index_buf[1] << 16)|(src_index_buf[2] << 8)|(src_index_buf[3]))) > attr_num) continue;
  560.         if (attr_num < MaxNum8bPartition - 1) {
  561.             putc(encode8b(index), i_out);
  562.         }
  563.         else if (attr_num < MaxNum16bPartition - 1) {
  564.             index = encode16b(index);
  565.             putc((index & 0x0000ff00) >> 8, i_out);
  566.             putc(index & 0x000000ff, i_out);
  567.         }
  568.         else {
  569.             fwrite(src_index_buf, 1, 4, i_out);    /* no reduction */
  570.         }
  571.             wordoffset = j = 4;
  572.         }
  573.         else wordoffset = j = 0;
  574.  
  575.         while ((j < REAL_INDEX_BUF) && (src_index_buf[j] != WORD_END_MARK) && (src_index_buf[j] != ALL_INDEX_MARK) && (src_index_buf[j] != '\n')) j++;
  576.         if ((j >= REAL_INDEX_BUF) || (src_index_buf[j] == '\n')) continue;
  577.         /* else it is WORD_END_MARK or ALL_INDEX_MARK */
  578.         c = src_index_buf[j+1];
  579.         src_index_buf[j+1] = '\0';
  580.         fputs(src_index_buf+wordoffset, i_out);
  581.         src_index_buf[j+1] = c;
  582.         if (src_index_buf[j] == ALL_INDEX_MARK) {
  583.         fputc(DONT_CONFUSE_SORT, i_out);
  584.         if (fputc('\n', i_out) == EOF) {
  585.             fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  586.             exit(2);
  587.         }
  588.         continue;
  589.         }
  590.  
  591.         offset = encode32b(part_size);
  592.         fputc((offset & 0xff000000) >> 24, i_out);    /* force big-endian */
  593.         fputc((offset & 0x00ff0000) >> 16, i_out);
  594.         fputc((offset & 0x0000ff00) >> 8, i_out);
  595.         fputc((offset & 0x000000ff), i_out);
  596.         if (fputc('\n', i_out) == EOF) {
  597.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  598.         exit(2);
  599.         }
  600.  
  601.         j++;    /* @first byte of the block numbers, actually = c */
  602.         while(src_index_buf[j] != '\n') {
  603.         fputc(src_index_buf[j++], p_out);
  604.         part_size ++;
  605.         }
  606.         if (fputc('\n', p_out) == EOF) {
  607.         fprintf(stderr, "Error: write failed at %s:%d\n", __FILE__, __LINE__);
  608.         exit(2);
  609.         }
  610.         part_size ++;
  611.     }
  612.     fclose(i_in);
  613.     fflush(i_out);
  614.     fclose(i_out);
  615.     sprintf(s, "mv %s/.glimpse_split.%d %s/%s", INDEX_DIR, getpid(), INDEX_DIR, INDEX_FILE);
  616.     system(s);
  617.     }
  618.     fflush(p_out);
  619.     fclose(p_out);
  620.  
  621.     /* Dump file names */
  622.     sprintf(s, "%s/%s", INDEX_DIR, NAME_LIST);
  623.     if((f_out = fopen(s, "w")) == NULL) {
  624.         fprintf(stderr, "can't open %s for writing\n", s);
  625.         exit(2);
  626.     }
  627.     for(i=0; i<file_num; i++) {
  628.     if (name_list[i] != NULL) fputs(name_list[i], f_out);
  629.     /* else empty line to indicate file that was removed = HOLE */
  630.     fputc('\n', f_out);
  631.     }
  632.     fflush(f_out);
  633.     fclose(f_out);
  634.  
  635.     return 0;
  636. }
  637.